package com.wyw.hemerocallis.util;

import com.alibaba.fastjson.JSON;
import com.wyw.hemerocallis.constant.CommonConstant;
import com.wyw.hemerocallis.vo.LoginUserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import sun.misc.BASE64Decoder;

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Calendar;

/**
 * JWT token解析工具类
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
public class TokenParseUtil {

    /**
     * 从JWT Token中解析LoginUserInfo对象
     *  如果不实用网关组件，可以在这里将token放入redis中，并针对性的处理
     * @param token     token值，若是错误的，没有必要处理
     * @return
     */
    public static LoginUserInfo parseUserInfoFromToken(String token) throws Exception{
        if(null == token){
            return null;
        }

        Jws<Claims> claimsJws = parseToken(token, getPublicKey());
        Claims body = claimsJws.getBody();

        if(body.getExpiration().before(Calendar.getInstance().getTime())){
            //token已经过期，返回null
            return null;
        }

        return JSON.parseObject(
                body.get(CommonConstant.JWT_USER_INFO_KEY).toString(),
                LoginUserInfo.class
        );
    }

    /**
     * 通过公钥解析token
     * @param token     token值
     * @param publicKey 公钥
     * @return
     */
    private static Jws<Claims> parseToken(String token, PublicKey publicKey) throws Exception{
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * 此处本地存储的公钥获取到PublicKey对象
     *  也可以放到数据库，但是就必须走鉴权服务进行解析
     *  也可以放到文件服务器中
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey() throws Exception{
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(
          new BASE64Decoder().decodeBuffer(CommonConstant.PUBLIC_KEY)
        );
        return KeyFactory.getInstance("RSA").generatePublic(keySpec);
    }
}
